package common

import (
	"log"
	"reflect"
	"strings"
	"time"
)

// SetStructFieldByJSONName 将结构体里的成员按照json名字来赋值
func SetStructFieldByJSONName(ptr interface{}, fields map[string]interface{}) {
	// log.Println("fields:", fields)

	v := reflect.ValueOf(ptr).Elem() // the struct variable

	for i := 0; i < v.NumField(); i++ {
		fieldInfo := v.Type().Field(i) // a reflect.StructField
		tag := fieldInfo.Tag           // a reflect.StructTag
		name := tag.Get("json")

		if name == "" {
			name = strings.ToLower(fieldInfo.Name)
		}

		// 去掉逗号后面内容 如 `json:"voucher_usage,omitempty"`
		name = strings.Split(name, ",")[0]
		// log.Println("JsonName:", name)

		if value, ok := fields[name]; ok {
			// log.Println("fieldInfo.Name:", fieldInfo.Name)
			// 给结构体赋值, 保证赋值时数据类型一致
			// log.Println("类型1：", reflect.ValueOf(value).Type(), "类型2：", v.FieldByName(fieldInfo.Name).Type())
			if reflect.ValueOf(value).Type() == v.FieldByName(fieldInfo.Name).Type() {
				// 从数据库取出来的原始数据, 只包括几种基本数据类型
				v.FieldByName(fieldInfo.Name).Set(reflect.ValueOf(value))
			} else if float64Value, ok := value.(float64); ok {
				// 当 float64 和 int64 不匹配的时候需要自己手动进行类型转换
				switch v.FieldByName(fieldInfo.Name).Type().Kind() {
				case reflect.Int:
					var temp = int(float64Value)
					v.FieldByName(fieldInfo.Name).Set(reflect.ValueOf(temp))
					break
				default:
					log.Println("json反序列化时未处理的类型转换", v.FieldByName(fieldInfo.Name).Type().Kind())
					break
				}
			} else if textValue, ok := value.(string); ok {
				switch v.FieldByName(fieldInfo.Name).Type().Kind() {
				case reflect.Struct:
					switch v.FieldByName(fieldInfo.Name).Type() {
					case reflect.TypeOf(time.Now()):
						if len(textValue) > len("2006-01-02 15:04:05") {
							textValue = textValue[:19]
						}
						loc, err := time.LoadLocation("Local")
						if err != nil {
							loc = time.UTC
						}
						tempTime, err := time.ParseInLocation("2006-01-02 15:04:05", textValue, loc)
						if err != nil {
							log.Println("json反序列化时处理类型转换失败", err)
						} else {

							v.FieldByName(fieldInfo.Name).Set(reflect.ValueOf(tempTime))
						}
					}
					break
				default:
					log.Println("json反序列化时未处理的类型转换", v.FieldByName(fieldInfo.Name).Type().Kind())
					break
				}
			}
		}
	}

	return
}
